#include "bsp_rtc.h"


/*RTC初始化*/
void rtc_init(void){
    /*设置RTC计数器开始计数的起始时间*/
    struct rtc_datetime rtcdate;
    rtcdate.year = 2025;
    rtcdate.month = 5;
    rtcdate.day = 22;
    rtcdate.hour = 22;
    rtcdate.minute = 0;
    rtcdate.second = 0;

    /*将起始时间转换为秒数写入到RTC计数器内*/
    rtc_setdatatime(&rtcdate);

    /*初始化RTC*/
    SNVS->HPCOMR = (1<<31) | (1<<8);
    rtc_enable();

}

/*开启RTC*/
void rtc_enable(void){
    SNVS->LPCR |= (1<<0);
    while ((SNVS->LPCR & 0X01) == 0);
}

/*关闭RTC*/
void rtc_disble(void){
    SNVS->LPCR &= ~(1<<0);
    while ((SNVS->LPCR & 0X01) == 1);
}

/*将年月日转换为时分秒*/
unsigned long long rtc_coverdate_to_second(struct rtc_datetime * datetime){
    unsigned short i = 0;
    unsigned int days = 0;
    unsigned long long seconds = 0;
    unsigned short monthdays[] = {0 , 0 , 31 , 59 , 90 , 120 , 151 , 181 , 212 , 243 , 273 , 304 , 334};
    
    /*将年换成天*/
    for(i = 1970 ; i < datetime->year ; i++){
        if(i%4 == 0){
            days = days+366;
        }else{
            days = days+365;
        }
    }

    /*将月换成天*/
    if((datetime->year)%4 == 0 && datetime->month>=3){
        days = days+monthdays[datetime->month]+1;
    }else{
        days = days+monthdays[datetime->month];
    }

    /*将天数对齐*/
    days = days + datetime->hour - 1;

    /*换算成秒*/
    seconds = days*SECONDS_IN_DAY + datetime->hour*SECONDS_IN_HOUR + datetime->minute*SECONDS_IN_MINUTE + datetime->second;
    return seconds;
}

/*向RTC计数器设置初始时间*/
void rtc_setdatatime(struct rtc_datetime * datetime){
    /*修改之前必须关闭RTC*/
    unsigned int tmp = SNVS->LPCR;
    rtc_disble();

    unsigned long long seconds = rtc_coverdate_to_second(datetime);
    SNVS->LPSRTCMR = (unsigned int)(seconds >> 17);
    SNVS->LPSRTCLR = (unsigned int)(seconds << 15);


    /*
    检测之前是否有打开RTC，如果没打开过，说明这是第一次设置值，还没有进行过RTC的初始化；那就先不要打开RTC，以防出错
    如果之前打开过说明一切配置都已经正确，这是在运行过程中需要修改参数，因此需要再次打开RTC
    */
    if((tmp & 0x01) == 1){
        rtc_enable();
    }
}

/*读取RTC计数器的时间*/
uint64_t rtc_getseconds(void){
    unsigned long long seconds = 0;
    seconds = SNVS->LPSRTCMR;
    seconds = (seconds << 17) |  (SNVS->LPSRTCLR >> 15);
    return seconds;
}


/*将RTC计数器的时间转换为年月日*/
void rtc_getdatetime(struct rtc_datetime * datetime ){
    uint64_t seconds = rtc_getseconds();
    unsigned short days = 0;
    unsigned short year = 1970;
    unsigned short i = 0;
    unsigned short monthdays[] = {0 , 0 , 31 , 59 , 90 , 120 , 151 , 181 , 212 , 243 , 273 , 304 , 334 , 365};
    unsigned short monthdays1[] = {0 , 0 , 31 , 60 , 91 , 121 , 152 , 182 , 213 , 244 , 274 , 305 , 335 , 366};
    while(1){
        if(year%4 == 0){
            if(seconds >= (DAYS_IN_A_YEAR+1)*SECONDS_IN_DAY){
                year = year+1;
                seconds = seconds - (DAYS_IN_A_YEAR+1)*SECONDS_IN_DAY;
            }else{
                datetime->year = year;
                break;
            }
        }else{
            if(seconds >= DAYS_IN_A_YEAR*SECONDS_IN_DAY){
                year = year+1;
                seconds = seconds - DAYS_IN_A_YEAR*SECONDS_IN_DAY;
            }else{
                datetime->year = year;
                break;
            }
        }
    }

    days = seconds/SECONDS_IN_DAY;
    seconds = seconds%SECONDS_IN_DAY;
    for(i=0 ; i<13 ; i++){
        if(datetime->year%4 == 0){
            if(days>=monthdays1[i] && days<monthdays1[i+1]){
                datetime->month = i;
                days = days - monthdays1[i];
                break;
            }
        }
        if(datetime->year%4 != 0){
            if(days>=monthdays[i] && days<monthdays[i+1]){
                datetime->month = i;
                days = days - monthdays[i];
                break;
            }
        }
    }

    datetime->day = days+1;
    datetime->hour = seconds/SECONDS_IN_HOUR;
    datetime->minute = (seconds - datetime->hour*SECONDS_IN_HOUR)/SECONDS_IN_MINUTE;
    datetime->second = seconds%SECONDS_IN_MINUTE;

}